// AWTList.cpp: implementation of the AWTList class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "awt.h"
#include "AWTList.h"
#include "AWTListPeer.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

IMPLEMENT_DYNAMIC(AWTList, AWTComponent)

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

AWTList::AWTList()
{
	construct(0, FALSE);
}

AWTList::AWTList(int rows)
{
	construct(rows, FALSE);
}

AWTList::AWTList(int rows, BOOL multipleMode)
{
	construct(rows, multipleMode);
}

AWTList::~AWTList()
{
//	while (!m_items.IsEmpty())
//		delete m_items.RemoveTail();
	if (m_selected != NULL)
		delete m_selected;

	if (m_actionListener != NULL)
	{
		if (m_actionListener->isMultiCaster())
		{
#ifdef UNDER_CE
			AWTEventMulticaster* mc = (AWTEventMulticaster*)m_actionListener;
#else
			AWTEventMulticaster* mc = dynamic_cast<AWTEventMulticaster*>(m_actionListener);
#endif
			delete mc;
		}
	}
	if (m_itemListener != NULL)
	{
		if (m_itemListener->isMultiCaster())
		{
#ifdef UNDER_CE
			AWTEventMulticaster* mc = (AWTEventMulticaster*)m_itemListener;
#else
			AWTEventMulticaster* mc = dynamic_cast<AWTEventMulticaster*>(m_itemListener);
#endif
			delete mc;
		}
	}
}

CString& AWTList::getItem(int index)
{
	if (index < -1 || index >= m_items.GetCount()) 
		return m_nullString;
	POSITION pos = m_items.FindIndex(index);	
	return m_items.GetAt(pos);
}

void AWTList::addItem(CString& item, int index) 
{
	if (index < -1 || index >= m_items.GetCount()) 
		index = -1;
	if (index == -1) 
	  m_items.AddTail(item);
	else 
		m_items.InsertAfter(m_items.FindIndex(index), item);
	if (m_peer != NULL)
		((AWTListPeer*)m_peer)->addItem(item, index);
}

void AWTList::replaceItem(CString& newValue, int index) 
{
	if (index >= m_items.GetCount())
		return;
	m_items.SetAt(m_items.FindIndex(index), newValue);
	if (m_peer != NULL)
		((AWTListPeer*)m_peer)->replaceItem(newValue, index);
}

void AWTList::clear() 
{
	if (m_peer != NULL)
		((AWTListPeer*)m_peer)->clear();
	m_items.RemoveAll();
}

void AWTList::remove(CString& item) 
{
	POSITION pos = m_items.GetHeadPosition();
	int n = 0;
	while (pos != NULL)
	{
		CString s = m_items.GetNext(pos);
		if (s == item)
		{
			remove(n);
		}
		n++;		
	}
}

int AWTList::getSelectedIndex() 
{
	AWTListPeer* peer = (AWTListPeer*)m_peer;
	if (m_peer != NULL)
	{
		int n = peer->getSelectedIndex();
		if (m_selected != NULL)
		{
			delete m_selected;
			m_selected = NULL;
		}
		if (n == -1)
		{
			m_selectedLength = 0;
			return n;	
		}
		m_selectedLength = 1;
		m_selected = new int[1];
		m_selected[0] = n;
		return n;
	}
	else
		return (m_selectedLength == 1) ? m_selected[0] : -1;
}

void AWTList::getSelectedIndexes(int** indexes, int* cnt) 
{
	AWTListPeer* peer = (AWTListPeer*)m_peer;
	if (peer != NULL) 
	{
    peer->getSelectedIndexes(indexes, cnt);
		m_selectedLength = *cnt;
		if (m_selected != NULL)
			delete m_selected;
		if (m_selectedLength == 0)
			m_selected = NULL;
		else
			m_selected = new int[m_selectedLength];	
		for (int n = 0; n < m_selectedLength; n++)
		{
			m_selected[n] = *indexes[n];	
		}
	}
	else
	{
		*cnt = m_selectedLength;
		if (*cnt > 0)
		{
			*indexes = new int[*cnt];
			for (int n = 0; n < *cnt; n++)
			{
				*indexes[n] = m_selected[n];
			}
		}		
	}
}

CString& AWTList::getSelectedItem() 
{
	int index = getSelectedIndex();
	return (index < 0) ? m_nullString : getItem(index);
}

CStringArray* AWTList::getSelectedItems() 
{
	int* indexes;
	int cnt;
	getSelectedIndexes(&indexes, &cnt);
	CStringArray* sel = new CStringArray();
	for (int n = 0; n < cnt; n++)
	{
		sel->Add(getItem(indexes[n]));
	}
	delete indexes;
	return sel;	
}

void AWTList::select(int index) 
{
	AWTListPeer* peer; 
	peer = (AWTListPeer*)m_peer; 
	if (m_peer != NULL) 
	{ 
		peer->select(index); 
//		return; 
	} 
           
	BOOL alreadySelected = FALSE; 

	for (int i = 0 ; i < m_selectedLength ; i++) 
	{ 
		if (m_selected[i] == index) 
		{ 
			alreadySelected = TRUE; 
			break; 
		} 
	} 

	if (!alreadySelected) 
	{ 
		if (!m_multipleMode) 
		{ 
			if (m_selected != NULL)
				delete m_selected;
			m_selected = new int[1]; 
			m_selected[0] = index; 
			m_selectedLength = 1;
		} 
		else 
		{ 
			int* newsel = new int[m_selectedLength + 1]; 
			for (int n = 0; n < m_selectedLength; n++)
				newsel[n] = m_selected[n];
			newsel[m_selectedLength] = index; 
			if (m_selected != NULL)
				delete m_selected;
      m_selected = newsel; 
			m_selectedLength++;
		} 
	} 
} 

void AWTList::select(CString& item)
{
	POSITION pos = m_items.GetHeadPosition();
	int n = 0;
	while (pos != NULL)
	{
		CString s = m_items.GetNext(pos);
		if (s == item)
		{
			select(n);
			return;
		}
		n++;		
	}
}

void AWTList::deselect(int index) 
{
	AWTListPeer* peer; 
	peer = (AWTListPeer*)m_peer; 
	if (peer != NULL) 
	{
	    peer->deselect(index);
	}

	for (int i = 0 ; i < m_selectedLength ; i++) 
	{
	  if (m_selected[i] == index) 
		{
			int* newsel = new int[m_selectedLength - 1];
			for (int n = 0; n < i; n++)
				newsel[n] = m_selected[n];
			for (int n = i; n < m_selectedLength; n++)
				newsel[n] = m_selected[n];
			if (m_selected != NULL)
				delete m_selected;
      m_selected = newsel; 
			m_selectedLength--;
			return;
		}
	}
}

BOOL AWTList::isSelected(int index) 
{
	int* indexes;
	int cnt;
	getSelectedIndexes(&indexes, &cnt);
	for (int i = 0 ; i < cnt ; i++) 
	{
		if (indexes[i] == index) 
		{
			delete indexes;
			return TRUE;
	  }
	}
	delete indexes;
	return FALSE;
}

void AWTList::setMultipleSelections(BOOL b) 
{
	if (b != m_multipleMode) 
	{
		m_multipleMode = b;
		AWTListPeer* peer = (AWTListPeer*)m_peer;
		if (peer != NULL) 
		{
			peer->setMultipleSelections(b);
    }
	}
}

void AWTList::makeVisible(int index) 
{
	m_visibleIndex = index;
		AWTListPeer* peer = (AWTListPeer*)m_peer;
		if (peer != NULL) 
	    peer->makeVisible(index);
}

void AWTList::delItems(int start, int end) 
{
	for (int i = end; i >= start; i--) 
	{
	    m_items.RemoveAt(m_items.FindIndex(i));
	}
	AWTListPeer* peer = (AWTListPeer*)m_peer;
	if (peer != NULL) 
	{
	  peer->delItems(start, end);
	}
}

CWnd* AWTList::createComponent()					 
{
	CWnd* wParent = getParent()->getPeer();
	if (wParent == NULL)
		return wParent;
	CListBox* pwnd = new AWTListPeer(this, m_multipleMode);
	DWORD dwStyle = WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_HSCROLL | WS_VSCROLL | LBS_NOINTEGRALHEIGHT;
	if (!m_b3DBorder)
		dwStyle |= WS_BORDER;
	if (m_multipleMode)
		dwStyle |= LBS_MULTIPLESEL;
	pwnd->Create(dwStyle, getBounds(), wParent, 0);
	if (m_b3DBorder)
		pwnd->ModifyStyleEx(0, WS_EX_CLIENTEDGE);
	pwnd->SetFont(CFont::FromHandle(m_font));
	POSITION pos = m_items.GetHeadPosition();
	while (pos != NULL)
	{
		((AWTListPeer*)pwnd)->addItem(m_items.GetNext(pos), -1);
	}
	for (int i = 0 ; i < m_selectedLength ; i++) 
	{
		if (m_multipleMode)
			pwnd->SetSel(m_selected[i]);
		else
			pwnd->SetCurSel(m_selected[i]);
	}

	if (!m_multipleMode)
		pwnd->SetTopIndex(m_selected[0]);

	if (!m_enabled)
		pwnd->EnableWindow(FALSE);

	return pwnd;
}

CSize AWTList::getMinimumSize()
{
	return getPreferredSize();
}

CSize AWTList::getPreferredSize()
{
	if (m_peer == NULL)
		return CSize(0,0);
	CListBox* pwnd = (CListBox*)m_peer;
	CDC* pdc = pwnd->GetDC();
	CFont* ft = CFont::FromHandle(m_font);
	CFont* ftOld = pdc->SelectObject(ft);
	TEXTMETRIC tm;
	pdc->GetTextMetrics(&tm);
	pdc->SelectObject(ftOld);
	pwnd->ReleaseDC(pdc);	
	CSize sz(100, (m_rows+1) * (tm.tmHeight + tm.tmExternalLeading));
	return sz;
}

void AWTList::processActionEvent(AWTActionEvent* e)
{
  if (m_actionListener != NULL) 
		m_actionListener->actionPerformed(e);
}

void AWTList::processItemEvent(AWTItemEvent* e)
{
  if (m_itemListener != NULL) 
		m_itemListener->itemStateChanged(e);
}



